package util;

import play.db.ebean.Model;

import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import java.lang.reflect.Field;
import java.util.UUID;

@MappedSuperclass
public class CModel extends Model {
    @Transient
    private boolean isMerged = false; // 游离对象merge后打标记，saveOrUpdate时调用update(id)

    @Override
    public void save() {
        if (getRecordUuid() == null) {
            String uuid = UUID.randomUUID().toString();
            setRecordUuid(uuid);
        }
        super.save();
        this.forceRefresh();
    }

    public void forceRefresh(Finder finder) {
        String uuid = this.getRecordUuid();
        Object record;
        if (this.getRecordId() != null && (Integer) this.getRecordId() > 0) {
            record = finder.where().eq("id", this.getRecordId()).findUnique();
        } else {
            record = finder.where().eq("uuid", uuid).findUnique();
        }
        if (record == null) {
            throw new RuntimeException("Can't find the record by uuid " + uuid);
        }
        Integer id = (Integer) Common.getPropertyOfObject(record, "id");
        Common.setPropertyOfObject(this, "id", id);
    }

    public void forceRefresh() {
        Finder finder = (Finder) Common.getStaticPropertyOfObject(this, "find");
        forceRefresh(finder);
    }

    /**
     * 将游离态对象当做持久化态处理，需要id有值
     */
    public void merge() {
        isMerged = true;
    }

    @Transient
    public void setRecordUuid(String uuid) {
        Common.setPropertyOfObject(this, "uuid", uuid);
    }

    @Transient
    public String getRecordUuid() {
        return (String) Common.getPropertyOfObject(this, "uuid");
    }

    @Transient
    public Object getRecordId() {
        Class cls = this.getClass();
        Field[] fields = cls.getDeclaredFields();
        Field idField = null;
        for (int i = 0; i < fields.length; ++i) {
            Field f = fields[i];
            if (f.isAnnotationPresent(Id.class)) {
                idField = f;
                break;
            }
        }
        if (idField == null) {
            throw new RuntimeException("Can't find the id field in the class");
        }
        try {
            return idField.get(this);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public void saveOrUpdate() {
        if (this.isMerged) {
            this.update(this.getRecordId());
        } else {
            this.save();
        }
    }

    public void dd(){
    }
}
